package com.wwdx.service.impl;

import com.google.common.collect.Lists;
import com.wwdx.BaseCommons;
import com.wwdx.model.WwdxBookModel;
import com.wwdx.model.WwdxOpenAuthModel;
import com.wwdx.model.WwdxVipUserModel;
import com.wwdx.model.WwdxWeixinUserModel;
import com.wwdx.service.TemplateMsgTaskServiceI;
import com.wwdx.utils.ConstantHolder;
import com.wwdx.wechat.WxConstant;
import lombok.Builder;
import lombok.Data;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.List;
import java.util.Set;

/**
 * @author liguoliang
 * @date 2018-03-12 16:21
 */
@Service
public class TemplateMsgTaskServiceImpl extends BaseCommons implements TemplateMsgTaskServiceI{

    @Override
    public void sendVipExpiresTemplate(){
        logger.info("分销商用户会员过期通知");
        List<WwdxVipUserModel> wwdxVipUserModels = wwdxVipUserService.find("from WwdxVipUserModel");
        int count = 0;
        for (WwdxVipUserModel wwdxVipUserModel : wwdxVipUserModels) {
            String openId = wwdxVipUserModel.getUnionid();
            //检测用户是否存在
            WwdxWeixinUserModel wwdxWeixinUserModel = wwdxWeixinUserService.getByOpenId(openId);
            if (wwdxWeixinUserModel == null){
                continue;
            }
            String appid = wwdxWeixinUserModel.getAppid();
            WwdxOpenAuthModel wwdxOpenAuthModel = wwdxOpenAuthService.getByAppId(appid);

            String merchantId;
            WxMpService wxMpService = wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appid);
            String nickname = wwdxWeixinUserModel.getNickname(), expireTime = wwdxVipUserModel.getExpireTime();
            int days = Days.daysBetween(new LocalDate(expireTime),new LocalDate()).getDays();
            List<String> list = Lists.newArrayList(wwdxVipUserModel.getEffectTime(),expireTime);

            String templateId;
            TemplateMsgDTO model;
            //检测商户是否绑定服务号
            if (wwdxOpenAuthModel == null){
                merchantId = WxConstant.OPENID;
                templateId = WxConstant.TEMPLATE_VIP_EXPIRE;
                model = TemplateMsgDTO.builder()
                        .keywords(list).templateId(templateId).openId(openId).build();
            }else {
                merchantId = wwdxOpenAuthModel.getOpenId();
                String key = String.format(ConstantHolder.MERCHANT_TEMPLATE_MAP, merchantId);
                templateId = (String) hashOperations.get(key, ConstantHolder.Constant.VIPEXPIRES_NOTICE);
                model = TemplateMsgDTO.builder()
                        .keywords(list).templateId(templateId).openId(openId).build();
            }

            String url,frist,remark;
            //过期前一天提醒
            if (days == -1) {
                frist = "亲爱的" + nickname + "，你的蜜读VIP听书卡即将过期。\n" +
                        "立即续费，继续与1%的终身学习者一起读书，让读书成为我们最好的老师，用阅读改写人生。\n";
                remark = "↓↓点击“详情”，邀请好友！";
                url = wxMpService.oauth2buildAuthorizationUrl(wechatUrl + "index.html?merchantId=" + merchantId, WxConsts.OAuth2Scope.SNSAPI_BASE, null);
                this.sendTemplate(wxMpService,model,frist,remark,url);
                count ++;
            }
        }
        logger.info("分销商用户会员过期通知,受影响行数：{}",count);
    }

    @Override
    public void sendVipPlanTemplate(WwdxBookModel wwdxBookModel,Integer phase){
        logger.info("会员学习计划通知");
        int count = 0;
        Boolean isAuthorizer = true;
        //会员用户
        List<WwdxVipUserModel> wwdxVipUserModels = wwdxVipUserService.find("from WwdxVipUserModel where subscribe=1");
        for (WwdxVipUserModel wwdxVipUserModel : wwdxVipUserModels) {
            String openId = wwdxVipUserModel.getUnionid();
            //检测用户是否存在
            WwdxWeixinUserModel wwdxWeixinUserModel = wwdxWeixinUserService.getByOpenId(openId);
            if (wwdxWeixinUserModel == null){
                continue;
            }
            String appid = wwdxWeixinUserModel.getAppid();
            //检测商户是否绑定服务号
            WwdxOpenAuthModel wwdxOpenAuthModel = wwdxOpenAuthService.getByAppId(appid);
            if (wwdxOpenAuthModel == null){
                isAuthorizer = false;
                continue;
            }
            try {
                WxMpService wxMpService = wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appid);
                WxMpUser wxMpUser = wxMpService.getUserService().userInfo(openId);
                if (wxMpUser == null || !wxMpUser.getSubscribe()){
                    continue;
                }
                this.execute(wxMpService,openId,wwdxOpenAuthModel.getNickName(),wwdxOpenAuthModel.getOpenId(),phase,wwdxBookModel,isAuthorizer);
                count ++;
            }catch (WxErrorException e){
                logger.error(e.getMessage());
            }
        }
        logger.info("会员学习计划通知,受影响行数：{}",count);
    }

    @Override
    public void execute(WxMpService wxMpService,String openId,String nickName,String merchantId,Integer phase,WwdxBookModel wwdxBookModel,Boolean isAuthorizer){
        String key = String.format(ConstantHolder.MERCHANT_TEMPLATE_MAP, merchantId);
        String templateId = (String) hashOperations.get(key, ConstantHolder.Constant.NEWBOOK_NOTICE);
        if (templateId == null && isAuthorizer == false)templateId = WxConstant.TEMPLATE_VIP_PLAN;
        TemplateMsgParamsDTO dto = TemplateMsgParamsDTO.builder()
                .openId(openId).bookname(wwdxBookModel.getBookname()).bookSummary(wwdxBookModel.getContentsummary())
                .phase(phase).templateId(templateId).merchantId(merchantId).wxMpService(wxMpService).build();
        this.execute(dto,nickName,isAuthorizer);
    }

    @Override
    public void sendSubscribeTemplate(WwdxBookModel wwdxBookModel,Integer phase){
        logger.info("分销商首页订阅用户通知");
        int count = 0;
        Boolean isAuthorizer = true;
        //商户列表
        Set<Object> members = setOperations.members(ConstantHolder.MERCHANT_SUBSCRIBE_SET);
        if (!CollectionUtils.isEmpty(members)){
            for (Object member : members) {
                String authorizerAppid = member.toString();
                //检测商户是否绑定服务号
                WwdxOpenAuthModel wwdxOpenAuthModel = wwdxOpenAuthService.getByAppId(authorizerAppid);
                WxMpService wxMpService = null;
                if (!WxConstant.APPID.equals(authorizerAppid)){
                    wxMpService = wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(authorizerAppid);
                }
                if (wwdxOpenAuthModel == null){
                    wwdxOpenAuthModel = new WwdxOpenAuthModel();
                    //是运营公众号时，直接指定
                    wwdxOpenAuthModel.setOpenId(WxConstant.TEMPLATE_VIP_PLAN);
                    wwdxOpenAuthModel.setNickName("蜜读学堂");
                    authorizerAppid = WxConstant.APPID;
                    isAuthorizer = false;
                }
                String key = String.format(ConstantHolder.MERCHANT_SUBSCRIBE_USER_SET, authorizerAppid);
                Set<Object> merchantUserList = setOperations.members(key);
                if (!CollectionUtils.isEmpty(merchantUserList)){
                    try {
                        for (Object mermber : merchantUserList) {
                            String openId = mermber.toString();
                            WxMpUser wxMpUser;
                            if (wxMpService!=null) {
                                wxMpUser = wxMpService.getUserService().userInfo(openId);
                                if (wxMpUser == null || !wxMpUser.getSubscribe()){
                                    continue;
                                }
                            }
                            this.execute(wxMpService,openId,wwdxOpenAuthModel.getNickName(),wwdxOpenAuthModel.getOpenId(),phase,wwdxBookModel,isAuthorizer);
                            count ++;
                        }
                    }catch (WxErrorException e){
                        logger.error(e.getMessage());
                    }
                }
            }
        }
        logger.info("分销商首页订阅用户通知,受影响行数：{}",count);
    }

    private synchronized void execute(TemplateMsgParamsDTO dto,String nickName,Boolean isAuthorizer) {
        String frist;
        String studyTime = new LocalDate().toString();
        List<String> list = Lists.newArrayList("蜜读听书为您解读第"+(100+dto.getPhase())+"本书",studyTime);
        TemplateMsgDTO model = TemplateMsgDTO.builder()
                .keywords(list).templateId(dto.getTemplateId()).openId(dto.getOpenId()).build();
        if (!isAuthorizer){
            frist = "晨听一本书，高效一整天，今日听书推荐：\n" +
                    "《"+dto.getBookname()+"》\n\n" + dto.getBookSummary()+"\n";
        }else {
            frist = "你关注的【"+nickName+"】今日为你推书：\n" +
                    "《"+dto.getBookname()+"》\n" + "\n"+"打开这本书，你的负面情绪一扫而光！" +"\n";
        }
        String remark = "一天一本书，碎片化时间，高效学习。\n" +
                "回复“TD”退订每日听书提醒，回复“DY”恢复提醒。";
        WxMpService wxMpService = dto.getWxMpService();
        String url;
        if (wxMpService!=null){
            url = wxMpService.oauth2buildAuthorizationUrl(wechatUrl + "index.html?merchantId=" + dto.getMerchantId(), WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);
        }else {
            url = wechatUrl+"auth.html?url="+wechatUrl+"index.html?merchantId=" + dto.getMerchantId();
        }
        this.sendTemplate(wxMpService,model,frist,remark,url);
    }

    private synchronized void sendTemplate(WxMpService service,TemplateMsgDTO model,String frist, String remark, String url){
        model.setFrist(frist);model.setRemark(remark);model.setUrl(url);
        WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                .templateId(model.getTemplateId()).url(model.getUrl()).toUser(model.getOpenId()).build();
        WxMpTemplateData firstData = new WxMpTemplateData("first", model.getFrist(),"#d43f3a");
        WxMpTemplateData remarkData = new WxMpTemplateData("remark", "\n"+model.getRemark(),"#576b95");
        templateMessage.addData(firstData).addData(remarkData);
        List<String> keywords = model.getKeywords();
        for (int i = 0; i < keywords.size(); i++) {
            WxMpTemplateData data = new WxMpTemplateData("keyword"+(i+1), keywords.get(i));
            templateMessage.addData(data);
        }
        try{
            if (service!=null){
                service.getTemplateMsgService().sendTemplateMsg(templateMessage);
            }else {
                merchantWxService.getTemplateMsgService().sendTemplateMsg(templateMessage);
            }
        }catch (WxErrorException e){
            logger.error("错误信息：{}",e.getMessage());
        }
    }

    /**
     * @author liguoliang
     */
    @Data
    @Builder
    private static class TemplateMsgDTO implements Serializable {
        private String openId,templateId,frist,remark,url;
        private List<String> keywords;
    }

    /**
     * @author liguoliang
     */
    @Data
    @Builder
    private static class TemplateMsgParamsDTO implements Serializable {
        private String openId,bookSummary,bookname,templateId,merchantId;
        private Integer phase;
        private WxMpService wxMpService;
    }
}